package com.elitel.frame.business.aspect;

import com.alibaba.fastjson.JSONObject;
import com.elitel.common.utils.RedisUtils;
import com.elitel.frame.business.annotation.DataCache;
import com.elitel.frame.main.entity.SysPrjservice;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import javax.servlet.ServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Collection;
import java.util.concurrent.TimeUnit;

import static com.elitel.common.constant.RedisKeyConstant.SERVER_INFO_KEY;


/**
 * @author mulis
 */
@Aspect
@Component
public class DataCacheAspect {
    private static final Logger logger = LoggerFactory.getLogger(DataCacheAspect.class);
    @Pointcut("@annotation(com.elitel.frame.business.annotation.DataCache)")
    public void pointcut() {
    }

    /**
     * 处理请求前执行
     */
    @Around(value = "pointcut() && @annotation(dataCache)", argNames = "joinPoint,dataCache")
    public Object doAround(ProceedingJoinPoint joinPoint, DataCache dataCache) throws Throwable {
        // 获取方法参数名称
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        Class returnType = signature.getReturnType();

        String[] parameterNames = signature.getParameterNames();
        // 获取方法中的参数
        Object[] args = joinPoint.getArgs();
        // 获取服务id是哪一个字段
        String serviceGuidField = dataCache.serviceGuidField();

        // 参数名称参数值组成json
        JSONObject params = getJsonObject(parameterNames, args);

        // 获取serviceGuidField在参数列表中的下标
        int serviceGuidFieldIndex = 0;
        for (int i = 0; i < parameterNames.length; i++) {
            if (serviceGuidField.equals(parameterNames[i])) {
                serviceGuidFieldIndex = i;
                break;
            }
        }


        Object res = new Object();
        if (args[serviceGuidFieldIndex] != null) {
            String serviceGuid = args[serviceGuidFieldIndex] + "";
            // 获取缓存中的服务
            Object serverInfo = RedisUtils.hGet(SERVER_INFO_KEY, serviceGuid);
            logger.info("服务id为：{}，获取缓存中的服务信息为：{}",serviceGuid, serverInfo);
            if (serverInfo != null) {

                SysPrjservice sysPrjservice = JSONObject.parseObject(serverInfo + "", SysPrjservice.class);
                Integer cacheDur = sysPrjservice.getCacheDur();
                if (cacheDur != null && cacheDur > 0) {
                    String paramStr = JSONObject.toJSONString(params).replace(" ", "")
                            .replace(":","=").replace("{","[").replace("}","]");
                    // 获取缓存中数据
                    Object cacheData = RedisUtils.get("SERVER_DATA:" + serviceGuid + ":" + paramStr);
                    if (cacheData != null) {
                        res = JSONObject.parseObject(cacheData + "", returnType);
                    } else {
                        // 执行查询逻辑
                        res = joinPoint.proceed(args);
                        // todo 错误数据不缓存
                        String jsonString = JSONObject.toJSONString(res);
                        logger.debug("缓存服务数据为：{}", jsonString);
                        JSONObject jsonObject = JSONObject.parseObject(jsonString);
                        Object code = jsonObject.get("code");
                        if (code != null && !"500".equals(code + "")) {
                            // 数据入缓存
                            RedisUtils.setEx("SERVER_DATA:" + serviceGuid +":"+ paramStr, jsonString, cacheDur, TimeUnit.SECONDS);
                            logger.info("缓存服务数据成功，服务id为：{}", serviceGuid);
                        }

                    }
                } else {
                    res =  joinPoint.proceed(args);
                }
            }
        }
        return res;


    }

    private static JSONObject getJsonObject(String[] parameterNames, Object[] args) {
        JSONObject params = new JSONObject();
        for (int i = 0; i < parameterNames.length; i++) {
            Object arg = args[i];
            if (arg instanceof ServletRequest || arg instanceof HttpServletResponse || arg == null || "".equals(arg)) {
                continue;
            }
            if (arg instanceof Collection) {
                Collection<?> collection = (Collection<?>) arg;
                if (collection.isEmpty()) {
                    continue;
                }
            }
            params.put(parameterNames[i], arg);
        }
        return params;
    }

}
